package com.tian.arch

import android.util.Log
import com.tian.arch.config.*
import com.tian.arch.function.http.HttpsTrustManager
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.TimeUnit

/**
 * okHttp,retrofit配置回调，用于定制化okhttp和retrofit
 */
typealias OkHttpConfig = (OkHttpClient.Builder) -> OkHttpClient.Builder
typealias RetrofitConfig = (Retrofit.Builder) -> Retrofit.Builder

/**
 * 全局配置提供者
 */
interface ConfigProvider {
    fun createGlobalConfig(): GlobalConfig
}

/**
 * 全局配置,这个对象一般由Application返回
 *
 * 使用方式如下
 * ```
 * class MyApplication : BaseApplication() {
 *
 *     override fun onCreate() {
 *          ...
 *     }
 *
 *     override fun createGlobalConfig():GlobalConfig {
 *          // 强烈建议 不要用 DefaultGlobalConfig,应该去app module中实现一个Config在返回
 *          return DefaultGlobalConfig.instance.config
 *     }
 * }
 * ```
 */
open class GlobalConfig {

    // 网络配置策略
    var networkPolicyProvider: NetworkPolicyProvider? = null

    // okhttp的配置
    var okhttpConfig: OkHttpConfig? = null

    // retrofit配置
    var retrofitConfig: RetrofitConfig? = null

    // toast工厂
    var toastFactory: ToastFactory = DefaultToastFactory.instance

    // 异常处理器
    var errorHandler: ErrorHandlerFactory = ToastErrorHandler.instance

    // 默认的显示委托
    var displayDelegate: DisplayDelegateFactory = DisplayFactory()

    companion object {
        /**
         *  提供给外部调用的创建方法，
         *
         *  ```
         *  参数为初始化器
         *    initializer:(GlobalConfig) -> Unit, 那么回调block中的引用就会变成it，如下
         *      GlobalConfig.create { it
         *         ...
         *      }
         *    initializer: GlobalConfig.() -> Unit，这样回调中block的引用就会变成this
         *      GlobalConfig.create { this
         *         ...
         *      }
         *  ```
         */
        fun create(initializer: GlobalConfig.() -> Unit): GlobalConfig {
            return GlobalConfig().apply(initializer)
        }
    }
}


/**
 * 提供一个 默认的GlobalConfig配置，正常来说还是希望 引入它的项目自己去利用 [GlobalConfig].create 去生成一个config
 */
class DefaultGlobalConfig private constructor() {

    val config = GlobalConfig.create {
        // 配置项网络策略
        networkPolicyProvider = object : NetworkPolicyProvider {
            override fun createNetworkPolicy(): INetworkConfigPolicy {
                return object : INetworkConfigPolicy {
                    private val rootUrl = "https://gateway-test.53zaixian.com/"
                    override fun getPolicyName(): String {
                        return BuildConfig.BUILD_TYPE
                    }

                    override fun getPolicyDomain(): String {
                        return rootUrl
                    }
                }
            }
        }
        // 配置okhttp
        okhttpConfig = {
            it.connectTimeout(30, TimeUnit.SECONDS)
                .writeTimeout(60, TimeUnit.SECONDS)
                .readTimeout(60, TimeUnit.SECONDS)
                .sslSocketFactory(HttpsTrustManager.createSSLSocketFactory(), HttpsTrustManager())
                .hostnameVerifier(HttpsTrustManager.TrustAllHostnameVerifier())
                .addInterceptor(HeaderInterceptor())
                .addInterceptor(loggerInterceptor)
        }
        retrofitConfig = {
            it.addConverterFactory(GsonConverterFactory.create())
            // 注掉掉对rxjava的适配
//                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        }

        // 可选配置项
//        displayDelegate = ...

    }

    companion object {
        private val instance by lazy { DefaultGlobalConfig() }
        fun customConfig(customBlock: (GlobalConfig) -> GlobalConfig): GlobalConfig {
            return customBlock(instance.config)
        }
    }

    private val loggerInterceptor = HttpLoggingInterceptor { message -> Log.d("http", message) }.apply {
        level = if (BuildConfig.BUILD_TYPE.equals("release", true)) {
            HttpLoggingInterceptor.Level.NONE
        } else {
            HttpLoggingInterceptor.Level.BODY
        }
    }


    private class HeaderInterceptor : Interceptor {

        override fun intercept(chain: Interceptor.Chain): Response {
            val originalRequest = chain.request()
            val requestBuilder: Request.Builder = originalRequest.newBuilder()
//        requestBuilder.addHeader(HEADER_USER_AGENT, DeviceInfoUtil.getUserAgent())
//        requestBuilder.addHeader(HEADER_VERSION, AppUtils.getAppVersionName())
//        requestBuilder.addHeader(HEADER_CHANNEL, ChannelUtil.getChannel())
//        requestBuilder.addHeader(HEADER_AUTH_TOKEN, "Bearer ${DataInfo.getInstance().token}")
            val request = requestBuilder.build()
            return chain.proceed(request)
        }

        companion object {
            private const val HEADER_AUTH_TOKEN: String = "AUTH-TOKEN"
            private const val HEADER_USER_AGENT: String = "userAgent"
            private const val HEADER_CHANNEL: String = "CHANNEL"
            private const val HEADER_VERSION: String = "version"
        }
    }
}




